package com.xuanyue.db.xuan.core.index;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.xuanyue.db.xuan.core.exception.IndexException;
import com.xuanyue.db.xuan.core.exception.SQLException;
import com.xuanyue.db.xuan.core.table.IBitIndex;
import com.xuanyue.db.xuan.core.table.IColumn;
import com.xuanyue.db.xuan.core.table.ISortElement;
import com.xuanyue.db.xuan.core.table.expr.Expr;
import com.xuanyue.db.xuan.core.table.expr.ExprValue;
import com.xuanyue.db.xuan.core.table.expr.ExprValueType;
import com.xuanyue.db.xuan.core.table.expr.SortTemplate;
import com.xuanyue.db.xuan.core.table.sort.SortElement;
import com.xuanyue.db.xuan.msg.VLAUETYPE;
/**
 * boolean数据列
 * @author 解观海
 * @email  guanhaixie@sina.cn
 * @date 2020年6月23日
 * @version 0.1
 */
public class BooleanIndex implements  IColumn{
//	private static Logger log= LoggerFactory.getLogger(BooleanIndex.class);
	private IBitIndex data = new BitIndex();
	private IBitIndex mask = new BitIndex();
	
	private String path;
	
	public IBitIndex getData() {
		return data;
	}

	@Override
	public boolean modify(IColumn newOne,boolean cpDataFromOld) {
		return false;
	}
	
	@Override
	public void setPath(String path) {
		this.path = path;
		data.setPath(String.format("%s/data", path));
		mask.setPath(String.format("%s/mask", path));
	}
	@Override
	public void flush(int maxId) {
		data.flush(maxId);
		mask.flush(maxId);
	}
	

	@Override
	public void set(int rowId,ExprValue value) {
		if(ExprValueType.BOOLEAN.is(value.getType())) {
			boolean v = value.getValue();
			data.set(rowId, v);
			mask.set(rowId, true);
		}else if(ExprValueType.NULL.is(value.getType())) {
			mask.set(rowId, false);
		}else {
			throw new SQLException("value type ERROR:"+value.getType()+"  is not a boolean value");
		}
	}

	@Override
	public Boolean get(int rowId) {
		return mask.get(rowId)?data.get(rowId):null;
	}

	@Override
	public ExprValue getExprValue(int rowId) {
		return new ExprValue(ExprValueType.BOOLEAN, get(rowId));
	}
	
	@Override
	public void save() {
		File p = new File(path);
		if(!p.exists()) {
			p.mkdirs();
		}
		data.save();
		mask.save();
	}

	@Override
	public void load()  {
		File p = new File(path);
		if(!p.exists()) {
			throw new IndexException(String.format("%s is not exists", path));
		}
		try {
			data.load();
			mask.load();
		} catch (Exception e) {
			throw new SQLException(e);
		}
		
	}
	@Override
	public void init() {
		File p = new File(path);
		if(!p.exists()) {
			p.mkdirs();
		}
		data.init();
		mask.init();
	}
	@Override
	public int getDataSize() {
		return 2;
	}
	@Override
	public List<ISortElement> getSortE(SortTemplate sortTemplate) {
		List<ISortElement> el = new ArrayList<ISortElement>();
		SortElement e = new SortElement();
		e.setData(mask);
		e.setDesc(sortTemplate.isDesc());
		el.add(e);
		
		e = new SortElement();
		e.setData(data);
		e.setDesc(sortTemplate.isDesc());
		el.add(e);
		
		return el;
	}
	@Override
	public VLAUETYPE getType() {
		return VLAUETYPE.BOOLEAN;
	}
	@Override
	public void saveRow(int rowId)  {
		data.saveRow( rowId);
		mask.saveRow( rowId);
	}
	@Override
	public boolean checkSortE(SortTemplate sortTemplate) {
		return sortTemplate.isType(SortTemplate.GENERAL);
	}
	@Override
	public boolean checkType(ExprValue v) {
		return ExprValueType.NULL.is(v.getType())||ExprValueType.BOOLEAN.is(v.getType());
	}
	@Override
	public void exe(Expr expr, List<IBitIndex> caches) {
		if(ExprValueType.BOOLEAN.is(expr.getValue().getType())) {
			boolean v = expr.getValue().getValue();
			caches.get(0).copyFrom(data);
			if("=".equals(expr.getOp())) {
				if(!v) {
					caches.get(0).not();
				}
				caches.get(0).and(mask);
			}else if("!=".equals(expr.getOp())){// !=
				if(v) {
					caches.get(0).not();
				}
				caches.get(0).orNot(mask);
			}else {
				throw new SQLException("the expr op is not supoort :"+ expr.getOp());
			}
		}else if(ExprValueType.NULL.is(expr.getValue().getType())) {
			if("=".equals(expr.getOp())) {
				caches.get(0).copyFrom(mask);
				caches.get(0).not();
			}else if("!=".equals(expr.getOp())) {
				caches.get(0).copyFrom(mask);
			}else {
				throw new SQLException("the expr op is not supoort :"+ expr.getOp());
			}
		}else {
			throw new SQLException("the expr value type is not supoort :"+ expr.getValue().getType());
		}
	}
	@Override
	public int checkAndContSource(Expr expr) {
		if(
				(
					ExprValueType.BOOLEAN.is(expr.getValue().getType())||
					ExprValueType.NULL.is(expr.getValue().getType())
				)&&(
					"=".equals(expr.getOp())||
					"!=".equals(expr.getOp())
				)
		){
			return 1;
		}
		return 0;
	}
	
	public IBitIndex getMask() {
		return this.mask;
	}
}
